package com.xuecheng.comment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.comment.model.dto.CommentDTO;
import com.xuecheng.api.comment.model.qo.CommentModel;
import com.xuecheng.api.comment.model.vo.CommentVO;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.comment.agent.ContentApiAgent;
import com.xuecheng.comment.common.constant.CommentErrorCode;
import com.xuecheng.comment.convert.CommentConvert;
import com.xuecheng.comment.convert.CommentReplyConvert;
import com.xuecheng.comment.entity.data.StarRankData;
import com.xuecheng.comment.mapper.CommentMapper;
import com.xuecheng.comment.service.CommentService;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.comment.entity.Comment;
import com.xuecheng.comment.entity.CommentReply;
import com.xuecheng.comment.mapper.CommentReplyMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {




    @Autowired
    private ContentApiAgent contentApiAgent;

    @Autowired
    private CommentReplyMapper commentReplyMapper;

    @Autowired
    private CommentMapper commentMapper;


    @Override
    //开启事务
    @Transactional
    public CommentDTO createComment(CommentDTO dto, String username) {

        //  2.核实关键信息
        //       2.1根据课程id（targetId）获取课程信息
        //new LambdaQueryWrapper<>();
        //       	2.1.1判断课程信息是否存在
        //       			不存在：抛出异常
        //       	2.1.2判断课程状态
        //       		只能是已经发布且在使用
        //dto转po，保存数据
        Comment po = CommentConvert.INSTANCE.dto2po(dto);
        //3.创建评论对象并设置属性值
        Comment comment = new Comment();
        //comment.setId(po.getId());
        //comment.setBelongTo(po.getBelongTo());
        comment.setComeFrom(po.getTargetId().toString());
        comment.setCommentDate(LocalDateTime.now());
        comment.setCommentText(po.getCommentText());

        comment.setNickName(po.getNickName());
        comment.setPraiseNum(po.getPraiseNum());
        comment.setStarRank(po.getStarRank());
        comment.setTargetId(po.getTargetId());

        comment.setTargetType(po.getTargetType());
        comment.setUserHead(po.getUserHead());
        comment.setUserId(po.getUserId());
        comment.setUserName(username);

        boolean b = this.save(comment);
        if (!b) {
            ExceptionCast.cast(CommonErrorCode.E_100106);
        }
        //po转dto，返回
        CommentDTO commentDTO = CommentConvert.INSTANCE.po2dto(comment);

        //        4.插入数据库，判断是否插入成功

        return commentDTO;
    }

    @Override
    @Transactional ( readOnly = true )
    public PageVO<CommentDTO> queryCommentList(PageRequestParams params, CommentModel commentModel) {
        getParamsTerm(params, commentModel);
        // 		1.3获取课程id
        // 				如果课程id为空则抛出异常
        Integer targetId = commentModel.getTargetId();
        if (ObjectUtils.isEmpty(targetId)) {
            ExceptionCast.cast(CommentErrorCode.E_180002);
        }

        //2.核实关键信息
        // 	 2.1根据课程id（targetId）获取课程信息
        // 				2.1.1判断课程信息是否存在
        // 						不存在：抛出异常
        // 				2.1.2判断课程状态
        // 						只能是已经发布且在使用

//        CourseBaseDTO courseBaseDTO = courseBaseApiAgent.getCourseBaseById(new Long(commentModel.getTargetId()));
//        if (ObjectUtils.isEmpty(courseBaseDTO)) {
//            ExceptionCast.cast(CommentErrorCode.E_180003);
//        }

        //3.设置查询条件

        LambdaQueryWrapper<Comment> queryWrapper = queryListTerm(commentModel);
        queryWrapper.eq(commentModel.getStarRank() != null, Comment::getStarRank, commentModel.getStarRank());
        queryWrapper.eq(commentModel.getUserId() != null, Comment::getUserId, commentModel.getUserId());
        queryWrapper.eq(StringUtil.isNotBlank(commentModel.getUserHead()), Comment::getUserHead, commentModel.getUserHead());
        queryWrapper.eq(StringUtil.isNotBlank(commentModel.getUserName()), Comment::getUserName, commentModel.getUserName());

        if (StringUtils.isNotBlank(commentModel.getReplyStatus()) && commentModel.getReplyStatus().equalsIgnoreCase("Y")) {
            queryWrapper.eq(Comment::getReplyStatus, Integer.parseInt(CommonEnum.USING_FLAG.getCode()));
        } else if (StringUtils.isNotBlank(commentModel.getReplyStatus()) && commentModel.getReplyStatus().equalsIgnoreCase("N")) {
            queryWrapper.eq(Comment::getReplyStatus, Integer.parseInt(CommonEnum.DELETE_FLAG.getCode()));
        }

        Long pageNo = params.getPageNo();
        Long pageSize = params.getPageSize();
        IPage<Comment> iPage = this.page(new Page<>(pageNo, pageSize), queryWrapper);

        List<Comment> commentList = iPage.getRecords();

        List<CommentDTO> commentDTOS = CommentConvert.INSTANCE.entitys2dtos(commentList);

        PageVO<CommentDTO> result = new PageVO<>(commentDTOS, iPage.getTotal(), iPage.getPages(), iPage.getSize());

        return result;
    }


    /**
     * 查询评论信息的数量统计
     *
     * @param targetId
     * @return
     */
    @Override
    public CommentVO queryNums(Long targetId) {
        //判断评论对象是否为空
        if (ObjectUtils.isEmpty(targetId)) {
            ExceptionCast.cast(CommentErrorCode.E_180004);
        }
        RestResponse<CourseBaseDTO> courseBaseDTO = contentApiAgent.getCourseBaseByTargetId(targetId);
        if (ObjectUtils.isEmpty(courseBaseDTO.getResult())) {
            ExceptionCast.cast(CommentErrorCode.E_180005);
        }
        if (!(courseBaseDTO.getResult().getAuditStatus().equals(CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode()))) {
            ExceptionCast.cast(CommentErrorCode.E_180006);
        }
        //查询总评论数
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Comment::getTargetId, targetId);
        Integer count = commentMapper.selectCount(queryWrapper);
        //查询平均数
        Float avg = commentMapper.selectAvgOfStar(targetId);
        //查询每个星级的数量
        List<StarRankData> starCount = commentMapper.selectCountOfStar(targetId);
        //数据封装
        CommentVO commentVO = new CommentVO();
        commentVO.setStarRank(avg.toString());
        commentVO.setTotalCommentNums(count);
        commentVO.setTargetId(new Integer(targetId.toString()));

        LambdaQueryWrapper<Comment> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Comment::getTargetId, targetId);
        List<Comment> commentList = this.list(queryWrapper1);
        Stream<Comment> stream1 = commentList.stream();
        commentVO.setStarRank1Nums((int) stream1.filter(comment -> comment.getStarRank().equals(1)).count());
        Stream<Comment> stream2 = commentList.stream();
        commentVO.setStarRank2Nums((int) stream2.filter(comment -> comment.getStarRank().equals(2)).count());
        Stream<Comment> stream3 = commentList.stream();
        commentVO.setStarRank3Nums((int) stream3.filter(comment -> comment.getStarRank().equals(3)).count());
        Stream<Comment> stream4 = commentList.stream();
        commentVO.setStarRank4Nums((int) stream4.filter(comment -> comment.getStarRank().equals(4)).count());
        Stream<Comment> stream5 = commentList.stream();
        commentVO.setStarRank5Nums((int) stream5.filter(comment -> comment.getStarRank().equals(5)).count());

        return commentVO;
    }

    private void getParamsTerm(PageRequestParams params, CommentModel commentModel) {
        //1.判断关键数据
        // 		1.1分页信息，评论查询信息是否存在
        // 				不存在：抛出异常
        if (ObjectUtils.isEmpty(commentModel)) {
            ExceptionCast.cast(CommentErrorCode.E_180002);
        }
        // 		1.2获取分页信息
        // 				如果分页信息中当前页码（pageNo)为空或者不合法（<1)则设置为1
        // 				如果分页信息中每页显示条数(pageSize)为空则设置为10
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
    }

    private LambdaQueryWrapper<Comment> queryListTerm(CommentModel commentModel) {
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        //判断课程id是否为空，不为空-添加查询条件
        queryWrapper.eq(commentModel.getTargetId() != null, Comment::getTargetId, commentModel.getTargetId());
        //判断课程名称是否为空，不为空-添加模糊查询
        if (StringUtils.isNotBlank(commentModel.getTargetName())) {
            queryWrapper.like(Comment::getTargetName, commentModel.getTargetName());
        }
        return queryWrapper;
    }

    @Override
    public PageVO<CommentDTO> queryCourseCommentList(PageRequestParams params, CommentModel commentModel) {
        //查询关键参数
        getParamsTerm(params, commentModel);

        //查询条件
        LambdaQueryWrapper<Comment> queryWrapper = queryListTerm(commentModel);

        //判断评星等级，不为空-》
        //      l=1  好评
        //      l=0  中评
        //      l=-1 差评
        if (!(ObjectUtils.isEmpty(commentModel.getLevel()))) {
            if (commentModel.getLevel().intValue() == 1) {
                queryWrapper.gt(Comment::getStarRank, 3);
            } else if (commentModel.getLevel().intValue() == 0) {
                queryWrapper.eq(Comment::getStarRank, 3);
            } else if (commentModel.getLevel().intValue() == -1) {
                queryWrapper.lt(Comment::getStarRank, 3);
            }
        }
        //判断是否可以评论
        //          Y->可以
        //          N->不可以
        if (StringUtils.isNotBlank(commentModel.getReplyStatus()) && commentModel.getReplyStatus().equalsIgnoreCase("Y")) {
            queryWrapper.eq(Comment::getReplyStatus, Integer.parseInt(CommonEnum.USING_FLAG.getCode()));
        } else if (StringUtils.isNotBlank(commentModel.getReplyStatus()) && commentModel.getReplyStatus().equalsIgnoreCase("N")) {
            queryWrapper.eq(Comment::getReplyStatus, Integer.parseInt(CommonEnum.DELETE_FLAG.getCode()));
        }
        //判断来至哪里
        queryWrapper.eq(StringUtil.isNotBlank(commentModel.getComeFrom()), Comment::getComeFrom, commentModel.getComeFrom());
        //判断状态
        queryWrapper.eq(Comment::getStatus, CommonEnum.USING_FLAG.getCodeInt());

        //创建分页对象
        Long pageNo = params.getPageNo();
        Long pageSize = params.getPageSize();
        IPage<Comment> iPage = this.page(new Page<>(pageNo, pageSize), queryWrapper);

        PageVO<CommentDTO> result = new PageVO<>(iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        if (iPage.getRecords() != null && iPage.getRecords().size() > 0) {
            List<CommentDTO> commentDTOS = CommentConvert.INSTANCE.entitys2dtos(iPage.getRecords());
            for (CommentDTO commentDTO : commentDTOS) {
                LambdaQueryWrapper<CommentReply> wrapper_1 = new LambdaQueryWrapper<>();
                wrapper_1.eq(CommentReply::getCommentId, commentDTO.getCommentId());
                List<CommentReply> commentReplies = commentReplyMapper.selectList(wrapper_1);
                commentDTO.setReplyDTOList(CommentReplyConvert.INSTANCE.entitys2dtos(commentReplies));
            }
            result.setItems(commentDTOS);
        }
        return result;
    }

    @Override
    public PageVO<CommentDTO> queryMCourseCommentList(PageRequestParams params) {
        //查询关键参数
        // 		1.2获取分页信息
        // 				如果分页信息中当前页码（pageNo)为空或者不合法（<1)则设置为1
        // 				如果分页信息中每页显示条数(pageSize)为空则设置为10
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        //查询条件
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();

        //判断状态
        queryWrapper.eq(Comment::getStatus, CommonEnum.USING_FLAG.getCodeInt());

        //创建分页对象
        Long pageNo = params.getPageNo();
        Long pageSize = params.getPageSize();
        IPage<Comment> iPage = this.page(new Page<>(pageNo, pageSize), queryWrapper);

        //封装查询信息并返回
        PageVO<CommentDTO> result = new PageVO<>(iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        if (iPage.getRecords() != null && iPage.getRecords().size() > 0) {
            List<CommentDTO> commentDTOS = CommentConvert.INSTANCE.entitys2dtos(iPage.getRecords());
            for (CommentDTO commentDTO : commentDTOS) {
                LambdaQueryWrapper<CommentReply> wrapper_1 = new LambdaQueryWrapper<>();
                wrapper_1.eq(CommentReply::getCommentId, commentDTO.getCommentId());
                List<CommentReply> commentReplies = commentReplyMapper.selectList(wrapper_1);
                commentDTO.setReplyDTOList(CommentReplyConvert.INSTANCE.entitys2dtos(commentReplies));
            }
            result.setItems(commentDTOS);
        }
        return result;
    }

    /**
     * 删除评论信息
     * @param commentId
     */
    @Transactional
    public void deleteComment(Long commentId) {
        //判断关键数据
        if (ObjectUtils.isEmpty(commentId)) {
            ExceptionCast.cast(CommentErrorCode.E_180002);
        }
        //根据ID获取评论信息
        Comment comment = this.getById(commentId);
        //判断评论信息是否存在
        if (ObjectUtils.isEmpty(comment)) {
            ExceptionCast.cast(CommentErrorCode.E_180009);
        }
        //判断评论信息是否删除
        if (comment.getStatus().equals(0)) {
            ExceptionCast.cast(CommentErrorCode.E_180010);
        }
        //逻辑删除评论信息
        LambdaUpdateWrapper<Comment> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Comment::getId, commentId);
        updateWrapper.set(Comment::getStatus, 0);
        boolean result = this.update(updateWrapper);
        //判断删除是否成功
        if (!result) {
            ExceptionCast.cast(CommentErrorCode.E_180011);
        }
    }

    /**
     *批量删除评论信息
     * @param request commentId拼接字符串
     */
    @Transactional
    public void deleteComments(String request) {
        //切割请求字符串获得评论ID数组
        String[] urls = request.split(",");
        //判断评论ID数组是否为空
        if (ObjectUtils.isEmpty(urls)) {
            ExceptionCast.cast(CommentErrorCode.E_180008);
        }
        //遍历数组获得每一个评论ID
        for (String url : urls) {
            Comment comment = this.getById(new Long(url));
            //判断评论信息是否存在
            if (ObjectUtils.isEmpty(comment)) {
                ExceptionCast.cast(CommentErrorCode.E_180009);
            }
            //判断评论信息是否删除
            if (ObjectUtils.isEmpty("0".equals(comment.getStatus().toString()))) {
                ExceptionCast.cast(CommentErrorCode.E_180010);
            }
            LambdaUpdateWrapper<Comment> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Comment::getId, new Long(url));
            updateWrapper.set(Comment::getStatus, 0);
            boolean result = this.update(updateWrapper);
            //判断是否删除成功
            if (ObjectUtils.isEmpty(result)) {
                ExceptionCast.cast(CommentErrorCode.E_180011);
            }
        }
    }

}
